package com.xiaoshuidi.cloud.module.rooms.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaoshuidi.cloud.framework.common.exception.ErrorCode;
import com.xiaoshuidi.cloud.framework.common.exception.ServiceException;
import com.xiaoshuidi.cloud.framework.common.pojo.CommonResult;
import com.xiaoshuidi.cloud.framework.common.pojo.PageResult;
import com.xiaoshuidi.cloud.framework.common.util.json.JsonUtils;
import com.xiaoshuidi.cloud.module.rooms.api.roomlayout.vo.GetRoomLayoutByApartmentRespVO;
import com.xiaoshuidi.cloud.module.rooms.controller.admin.pricing.vo.LayoutPricingPageReq;
import com.xiaoshuidi.cloud.module.rooms.controller.admin.pricing.vo.LayoutPricingPageResp;
import com.xiaoshuidi.cloud.module.rooms.controller.admin.roomel.vo.RoomelUpdateReqVO;
import com.xiaoshuidi.cloud.module.rooms.controller.admin.roomlayout.vo.*;
import com.xiaoshuidi.cloud.module.rooms.convert.roomlayout.RoomLayoutConvert;
import com.xiaoshuidi.cloud.module.rooms.mapper.RoomLayoutMapper;
import com.xiaoshuidi.cloud.module.rooms.mq.producer.RoomEsProducer;
import com.xiaoshuidi.cloud.module.rooms.pojo.Apartment;
import com.xiaoshuidi.cloud.module.rooms.pojo.RoomHouse;
import com.xiaoshuidi.cloud.module.rooms.pojo.RoomHouseType;
import com.xiaoshuidi.cloud.module.rooms.pojo.RoomLayout;
import com.xiaoshuidi.cloud.module.rooms.repository.ApartmentRepository;
import com.xiaoshuidi.cloud.module.rooms.repository.RoomHouseRepository;
import com.xiaoshuidi.cloud.module.rooms.repository.RoomHouseTypeRepository;
import com.xiaoshuidi.cloud.module.rooms.repository.RoomLayoutRepository;
import com.xiaoshuidi.cloud.module.rooms.service.RoomLayoutService;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 房型信息 服务实现类
 * </p>
 *
 * @author hans.zhang
 * @since 2023-05-06
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RoomLayoutServiceImpl extends ServiceImpl<RoomLayoutMapper, RoomLayout> implements RoomLayoutService {

    private final RoomLayoutRepository roomLayoutRepository;
    private final RoomHouseTypeRepository roomHouseTypeRepository;
    private final ApartmentRepository apartmentRepository;
    private final RoomHouseRepository roomHouseRepository;
    private final RoomEsProducer roomEsProducer;

    /**
     * 删除房型
     *
     * @param id 房型id
     * @return
     */
    @Override
    public CommonResult<Boolean> delete(@NonNull Long id) {
        RoomLayout roomLayout = roomLayoutRepository.getById(id);
        Assert.isTrue(ObjectUtil.isNotEmpty(roomLayout), "房型信息不存在");

        // 检查房型下是否有房间
        List<RoomHouse> roomHouses = roomHouseRepository.getByLayoutId(id);
        Assert.isTrue(ObjectUtil.isEmpty(roomHouses), "该房型下有房间，不可删除");

        roomLayoutRepository.removeById(id);
        return CommonResult.success(Boolean.TRUE);
    }

    /**
     * 分页查询
     *
     * @param pageSize 每页大小
     * @param pageNum  第几页
     * @return
     */
    @Override
    public CommonResult<PageResult<RoomLayoutPageRespVO>> pageList(Integer pageSize, Integer pageNum, Long apartmentId) {
        // 分页查询公寓下的所有房型
        LambdaQueryWrapper<RoomLayout> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(apartmentId != null, RoomLayout::getApartmentId, apartmentId);
        Page<RoomLayout> page = roomLayoutRepository.page(new Page<>(pageNum, pageSize), wrapper);
        List<RoomLayoutPageRespVO> respVOS = RoomLayoutConvert.INSTANCE.convert(page.getRecords());
        respVOS.stream().forEach(p -> {
            List<RoomHouse> roomHouses = roomHouseRepository.getByLayoutId(p.getId());
            RoomHouseType roomHouseType = roomHouseTypeRepository.getById(p.getRoomHouseTypeId());
            p.setRoomHouseNum(roomHouses.size());
            p.setRoomHouseTypeName(ObjectUtil.isNotEmpty(roomHouseType) ? roomHouseType.getName() : "");
        });
        PageResult<RoomLayoutPageRespVO> result = new PageResult<>(respVOS, page.getTotal());
        return CommonResult.success(result);
    }

    /**
     * 添加房型
     *
     * @param roomLayoutReqVO
     * @return 房型id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<RoomLayoutRespVO> create(RoomLayoutReqVO roomLayoutReqVO) {
        Apartment apartment = apartmentRepository.getById(roomLayoutReqVO.getApartmentId());
        Assert.isTrue(ObjectUtil.isNotEmpty(apartment), "公寓信息不存在");
        if(ObjectUtil.isEmpty(apartment.getIsConcentrated())){
            throw new ServiceException(new ErrorCode(20045, "请先维护门店信息"));
        }
        if(!apartment.getIsConcentrated()){
            throw new ServiceException(new ErrorCode(20045, "集中式门店才可维护房型"));
        }
        // 房型面积限制两位小数点
        if (BigDecimal.valueOf(roomLayoutReqVO.getSpaceMin()).scale() > 2 || BigDecimal.valueOf(roomLayoutReqVO.getSpaceMax()).scale() > 2) {
            throw new ServiceException(new ErrorCode(20044, "面积小数位不能超过两位"));
        }

        Assert.isTrue(roomLayoutReqVO.getSpaceMin() <= roomLayoutReqVO.getSpaceMax(), "面积最小值不能超过最大值");

        // 检查户型是否存在
        RoomHouseType roomHouseType = roomHouseTypeRepository.getLayout(
                // 卧室
                roomLayoutReqVO.getBedRoomNum(),
                // 客厅
                roomLayoutReqVO.getLivingRoomNum(),
                // 卫生间
                roomLayoutReqVO.getToiletNum(),
                // 厨房
                roomLayoutReqVO.getKitchenNum(),
                // 阳台
                roomLayoutReqVO.getBalcony()
        );

        // 户型不存在则创建户型
        if (ObjectUtil.isEmpty(roomHouseType)) {
            roomHouseType = new RoomHouseType();
            roomHouseType.setBedRoomNum(roomLayoutReqVO.getBedRoomNum());
            roomHouseType.setLivingRoomNum(roomLayoutReqVO.getLivingRoomNum());
            roomHouseType.setToiletNum(roomLayoutReqVO.getToiletNum());
            roomHouseType.setKitchenNum(roomLayoutReqVO.getKitchenNum());
            roomHouseType.setBalcony(roomLayoutReqVO.getBalcony());
            StringBuilder name = new StringBuilder();
            if (roomHouseType.getBedRoomNum() != null && roomHouseType.getBedRoomNum() > 0) {
                name.append(roomHouseType.getBedRoomNum());
                name.append("室");
            }
            if (roomHouseType.getLivingRoomNum() != null && roomHouseType.getLivingRoomNum() > 0) {
                name.append(roomHouseType.getLivingRoomNum());
                name.append("厅");
            }
            if (roomHouseType.getKitchenNum() != null && roomHouseType.getKitchenNum() > 0) {
                name.append(roomHouseType.getKitchenNum());
                name.append("厨");
            }
            if (roomHouseType.getToiletNum() != null && roomHouseType.getToiletNum() > 0) {
                name.append(roomHouseType.getToiletNum());
                name.append("卫");
            }
            if (roomHouseType.getBalcony() != null && roomHouseType.getBalcony() > 0) {
                name.append(roomHouseType.getBalcony());
                name.append("阳台");
            }
            roomHouseType.setName(name.toString());
            roomHouseTypeRepository.save(roomHouseType);
        }

        // 检查房型名称是否重复
        RoomLayout layout = roomLayoutRepository.getByApartmentIdAndName(roomLayoutReqVO.getApartmentId(), roomLayoutReqVO.getName());
        Assert.isTrue(ObjectUtil.isEmpty(layout), "房型名称已存在,请修改名称");
        // 创建房型
        RoomLayout roomLayout = RoomLayoutConvert.INSTANCE.convert(roomLayoutReqVO);
        roomLayout.setApartmentId(roomLayoutReqVO.getApartmentId());
        roomLayout.setRoomHouseTypeId(roomHouseType.getId());
        roomLayout.setDeptId(apartment.getDeptId());
        roomLayoutRepository.save(roomLayout);
        return CommonResult.success(RoomLayoutRespVO.builder().id(roomLayout.getId()).build());
    }

    /**
     * 编辑房型
     *
     * @param roomLayoutEditReqVO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<RoomLayoutRespVO> edit(RoomLayoutEditReqVO roomLayoutEditReqVO) {
        RoomLayout roomLayout = roomLayoutRepository.getById(roomLayoutEditReqVO.getId());
        Assert.isTrue(ObjectUtil.isNotEmpty(roomLayout), "房型信息不存在");

        Apartment apartment = apartmentRepository.getById(roomLayoutEditReqVO.getApartmentId());
        Assert.isTrue(ObjectUtil.isNotEmpty(apartment), "公寓信息不存在");

        // 检查房型名称是否重复
        RoomLayout layout = roomLayoutRepository.getByApartmentIdAndName(roomLayoutEditReqVO.getApartmentId(), roomLayoutEditReqVO.getName());
        Assert.isTrue(ObjectUtil.isEmpty(layout) || layout.getId().equals(roomLayoutEditReqVO.getId()), "房型名称已存在,请修改名称");

        // 房型面积限制两位小数点
        if (BigDecimal.valueOf(roomLayoutEditReqVO.getSpaceMin()).scale() > 2 || BigDecimal.valueOf(roomLayoutEditReqVO.getSpaceMax()).scale() > 2) {
            throw new ServiceException(new ErrorCode(20044, "面积小数位不能超过两位"));
        }

        Assert.isTrue(roomLayoutEditReqVO.getSpaceMin() <= roomLayoutEditReqVO.getSpaceMax(), "面积最小值不能超过最大值");

        // 检查户型是否存在
        RoomHouseType roomHouseType = roomHouseTypeRepository.getLayout(
                // 卧室
                roomLayoutEditReqVO.getBedRoomNum(),
                // 客厅
                roomLayoutEditReqVO.getLivingRoomNum(),
                // 卫生间
                roomLayoutEditReqVO.getToiletNum(),
                // 厨房
                roomLayoutEditReqVO.getKitchenNum(),
                // 阳台
                roomLayoutEditReqVO.getBalcony()
        );

        // 户型不存在则创建户型
        if (ObjectUtil.isEmpty(roomHouseType)) {
            roomHouseType = new RoomHouseType();
            roomHouseType.setBedRoomNum(roomLayoutEditReqVO.getBedRoomNum());
            roomHouseType.setLivingRoomNum(roomLayoutEditReqVO.getLivingRoomNum());
            roomHouseType.setToiletNum(roomLayoutEditReqVO.getToiletNum());
            roomHouseType.setKitchenNum(roomLayoutEditReqVO.getKitchenNum());
            roomHouseType.setBalcony(roomLayoutEditReqVO.getBalcony());
            StringBuilder name = new StringBuilder();
            if (roomHouseType.getBedRoomNum() != null && roomHouseType.getBedRoomNum() > 0) {
                name.append(roomHouseType.getBedRoomNum());
                name.append("室");
            }
            if (roomHouseType.getLivingRoomNum() != null && roomHouseType.getLivingRoomNum() > 0) {
                name.append(roomHouseType.getLivingRoomNum());
                name.append("厅");
            }
            if (roomHouseType.getKitchenNum() != null && roomHouseType.getKitchenNum() > 0) {
                name.append(roomHouseType.getKitchenNum());
                name.append("厨");
            }
            if (roomHouseType.getToiletNum() != null && roomHouseType.getToiletNum() > 0) {
                name.append(roomHouseType.getToiletNum());
                name.append("卫");
            }
            if (roomHouseType.getBalcony() != null && roomHouseType.getBalcony() > 0) {
                name.append(roomHouseType.getBalcony());
                name.append("阳台");
            }
            roomHouseType.setName(name.toString());
            roomHouseTypeRepository.save(roomHouseType);
        }

        roomLayout = RoomLayoutConvert.INSTANCE.convert(roomLayoutEditReqVO);
        roomLayout.setApartmentId(roomLayoutEditReqVO.getApartmentId());
        roomLayout.setRoomHouseTypeId(roomHouseType.getId());
        roomLayoutRepository.updateById(roomLayout);

        List<RoomelUpdateReqVO> roomelUpdateReqVOS = new ArrayList<>();
        // 将房型关联的房源查询出，同步户型信息到es
        List<RoomHouse> roomHouses = roomHouseRepository.getByRoomLayoutId(roomLayout.getId());
        for (RoomHouse roomHouse : roomHouses) {
            roomHouse.setRoomHouseTypeId(roomHouseType.getId());

            RoomelUpdateReqVO roomelUpdateReqVO = new RoomelUpdateReqVO();
            roomelUpdateReqVO.setId(roomHouse.getId());
            roomelUpdateReqVO.setBedroomNum(roomHouseType.getBedRoomNum());
            roomelUpdateReqVO.setLivingroomNum(roomHouseType.getLivingRoomNum());
            roomelUpdateReqVO.setKitchenNum(roomHouseType.getKitchenNum());
            roomelUpdateReqVO.setToiletNum(roomHouseType.getToiletNum());
            roomelUpdateReqVO.setBalcony(roomHouseType.getBalcony());
            roomelUpdateReqVO.setRoomHouseTypeId(roomHouseType.getId());
            roomelUpdateReqVO.setRoomHouseTypeName(roomHouseType.getName());
            roomelUpdateReqVO.setLayoutName(roomLayout.getName());
            roomelUpdateReqVOS.add(roomelUpdateReqVO);
        }
        roomHouseRepository.updateBatchById(roomHouses);
        // 更新房源信息到es
        roomEsProducer.updateBatchRoomEl(roomelUpdateReqVOS);

        return CommonResult.success(RoomLayoutRespVO.builder().id(roomLayout.getId()).build());
    }

    @Override
    public CommonResult<RoomLayoutDetailRespVO> detail(@NonNull Long id) {
        RoomLayout roomLayout = roomLayoutRepository.getById(id);
        Assert.isTrue(ObjectUtil.isNotEmpty(roomLayout), "房型信息不存在");
        RoomLayoutDetailRespVO respVO = RoomLayoutConvert.INSTANCE.convert(roomLayout);
        RoomHouseType roomHouseType = roomHouseTypeRepository.getById(roomLayout.getRoomHouseTypeId());
        respVO.setRoomHouseTypeName(ObjectUtil.isNotEmpty(roomHouseType) ? roomHouseType.getName() : "");
        respVO.setBedRoomNum(roomHouseType.getBedRoomNum());
        respVO.setLivingRoomNum(roomHouseType.getLivingRoomNum());
        respVO.setToiletNum(roomHouseType.getToiletNum());
        respVO.setKitchenNum(roomHouseType.getKitchenNum());
        respVO.setBalcony(roomHouseType.getBalcony());
        return CommonResult.success(respVO);
    }

    @Override
    public PageResult<LayoutPricingPageResp> pricingLayoutPage(LayoutPricingPageReq req) {

        List<Long> layoutIds = null;
        //如果房源编号不为空，则先根据房源信息获取房型ID
        if (StrUtil.isNotEmpty(req.getHouseNo())) {
            layoutIds = roomHouseRepository.distinctLayoutId(req.getApartmentId(), req.getHouseNo());
            if (CollectionUtil.isEmpty(layoutIds)) {
                return null;
            }
        }
        IPage<RoomLayout> page = roomLayoutRepository.page1(req.getPageSize(), req.getPageNo(), req.getApartmentId(), layoutIds, req.getConfig());
        List<LayoutPricingPageResp> list = page.getRecords().stream().map(s -> {
            LayoutPricingPageResp resp = new LayoutPricingPageResp();
            resp.setId(s.getId())
                    .setName(s.getName())
                    .setMonthRental(s.getMonthRental())
                    .setApartmentId(s.getApartmentId());
            return resp;
        }).collect(Collectors.toList());
        PageResult<LayoutPricingPageResp> result = new PageResult<>(list, page.getTotal());
        return result;
    }

    /**
     * 获取公寓下所有房型
     *
     * @param apartmentId
     * @return
     */
    @Override
    public CommonResult<List<RoomLayoutRespVO>> getList(@NonNull Long apartmentId) {
        apartmentRepository.myGetById(apartmentId);
        List<RoomLayoutRespVO> respVOS = new ArrayList<>();
        List<RoomLayout> roomLayouts = roomLayoutRepository.getByApartmentId(apartmentId);
        roomLayouts.stream().forEach(roomLayout -> {
            respVOS.add(RoomLayoutRespVO.builder().id(roomLayout.getId()).name(roomLayout.getName()).build());
        });
        return CommonResult.success(respVOS);
    }

    /**
     * 根据门店id列表获取房型信息
     * @return
     */
    @Override
    public List<GetRoomLayoutByApartmentRespVO> getRoomLayoutByApartments(List<Long> ids, Integer count) {
        List<GetRoomLayoutByApartmentRespVO> roomLayouts = roomLayoutRepository.getRoomLayoutByApartments(ids);
        if(ObjectUtil.isNotEmpty(count)){
            roomLayouts = RandomUtil.randomEleList(roomLayouts, count);
        }
        return roomLayouts;
    }

}
